package com.valuedaas.schoolsafety.service.recources;

import com.mongodb.client.model.Projections;
import com.mongodb.client.model.Updates;
import com.valuedaas.schoolsafety.common.collects.sys.SysInterface;
import com.valuedaas.schoolsafety.common.collects.sys.SysMenu;
import com.valuedaas.schoolsafety.common.collects.sys.SysRole;
import com.valuedaas.schoolsafety.common.collects.sys.SysUser;
import com.valuedaas.schoolsafety.common.enums.DataStatus;
import com.valuedaas.schoolsafety.common.enums.FixedRoles;
import com.valuedaas.schoolsafety.controller.user.vo.User;
import com.valuedaas.schoolsafety.service.BaseService;
import org.apache.commons.lang3.StringUtils;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service("sysRoleService")
public class RoleService extends BaseService {

    public static Logger log = LoggerFactory.getLogger(RoleService.class);

    @Autowired
    MenuService menuService;

    @Autowired
    InterfaceService interfaceService;

    @Override
    protected String collName() {
        return SysRole.COLL_NAME;
    }


    /**
     * 获取角色详情
     *
     * @param roleIdStr
     * @return
     */
    public Document getSocialUnitRole(String roleIdStr) {
        ObjectId roleId = new ObjectId(roleIdStr);
        Document doc = mongoTemplate.getCollection(SysRole.COLL_NAME).find(new Document(SysRole._ID, roleId).append(SysRole.STATUS, DataStatus.NORMAL)).first();
        return doc;
    }

    /**
     * 获取单位所有角色
     *
     * @param unitId
     * @return
     */
    public List<Document> listSocialUnitRoles(String unitId) {
        List<Document> list = new ArrayList<Document>();
        mongoTemplate.getCollection(SysRole.COLL_NAME)
                .find(new Document(SysRole.STATUS, 0)).into(list);
        return list;
    }

    /**
     * 获取所有角色
     *
     * @return
     */
    public List<Document> listSocialUnitRoles() {
        List<Document> list = new ArrayList<Document>();
        mongoTemplate.getCollection(SysRole.COLL_NAME).find(new Document(SysRole.STATUS, 0)).into(list);
        return list;
    }

    /**
     * 获取所有角色
     *
     * @param roleNames
     * @return
     */
    public List<Document> listSocialUnitRoles(List<String> roleNames) {
        List<Document> list = new ArrayList<Document>();
        mongoTemplate.getCollection(SysRole.COLL_NAME)
                .find(new Document(SysRole.STATUS, 0).append(SysRole.NAME, new Document("$in", roleNames)))
                .projection(new Document(SysRole.NAME, 1).append(SysRole.KEY, 1)).into(list);
        return list;
    }


    /**
     * 检查角色名是否存在
     *
     * @param name
     * @param unitId
     * @return
     */
    public boolean checkRoleByName(String name, String unitId) {
        return mongoTemplate.getCollection(SysRole.COLL_NAME)
                .count(new Document(SysRole.NAME, name).append(SysRole.STATUS, DataStatus.NORMAL)) > 0;
    }

    /**
     * 获取角色
     *
     * @param name
     * @return
     */
    public Document getRoleByName(String name) {
        return mongoTemplate.getCollection(SysRole.COLL_NAME).find(new Document(SysRole.NAME, name)
                .append(SysRole.STATUS, DataStatus.NORMAL))
                .first();
    }

    /**
     * 获取所有固定角色map （key为 角色名称， value 为角色ObjectId
     *
     * @return
     */
    public Map<String, ObjectId> getFixedRoleNameMap() {
        List<String> names = new ArrayList<>();
        for (FixedRoles en : FixedRoles.values()) {
            names.add(en.name());
        }
        List<Document> dList = new ArrayList<>();
        Document filter = new Document(SysRole.NAME, new Document("$in", names)).append(SysRole.STATUS,
                DataStatus.NORMAL);
        mongoTemplate.getCollection(SysRole.COLL_NAME).find(filter).into(dList);

        Map<String, ObjectId> map = new HashMap<>();
        if (dList != null) {
            dList.forEach((d) -> {
                map.put(d.getString(SysRole.NAME), d.getObjectId(SysRole._ID));
            });
        }
        return map;
    }


    /**
     * 获取所有固定角色map （key为角色 ObjectId， value 为角色名称
     *
     * @return
     */
    public Map<ObjectId, String> getFixedRoleIdMap() {
        List<String> names = new ArrayList<>();
        for (FixedRoles en : FixedRoles.values()) {
            names.add(en.name());
        }
        List<Document> dList = new ArrayList<>();
        Document filter = new Document(SysRole.NAME, new Document("$in", names)).append(SysRole.STATUS,
                DataStatus.NORMAL);
        mongoTemplate.getCollection(SysRole.COLL_NAME).find(filter).into(dList);

        Map<ObjectId, String> map = new HashMap<>();
        if (dList != null) {
            dList.forEach((d) -> {
                map.put(d.getObjectId(SysRole._ID), d.getString(SysRole.NAME));
            });
        }
        return map;
    }


    /**
     * 获取角色
     *
     * @param name
     * @param unitId
     * @return
     */
    public Document getRoleByName(String name, String unitId) {
        return mongoTemplate.getCollection(SysRole.COLL_NAME).find(new Document(SysRole.NAME, name)
                .append(SysRole.STATUS, DataStatus.NORMAL))
                .first();
    }


    /**
     * 添加一个新的角色信息
     *
     * @param roleName
     * @param roleDesc
     * @param unitId
     */
    public void addRole(String roleName, String roleDesc, String unitId) {
        mongoTemplate.getCollection(SysRole.COLL_NAME).insertOne(new Document(SysRole.NAME, roleName)
                .append(SysRole.DESC, roleDesc).append(SysRole.STATUS, 0));
    }

    /**
     * 添加一个新的角色信息
     *
     * @param d
     */
    public void addRole(Document d) {
        mongoTemplate.getCollection(SysRole.COLL_NAME).insertOne(d);
    }

    /**
     * 检查角色是否还有人在用
     *
     * @param unitId
     * @param roleId
     * @return
     */
    public boolean hasRoleUser(String unitId, String roleId) {
        ObjectId orgObjId = new ObjectId(unitId);
        ObjectId roleObjId = new ObjectId(roleId);

        long count = mongoTemplate.getCollection(SysUser.COLL_NAME).count(new Document(SysUser.UNITID, orgObjId).append(SysUser.ROLES, roleObjId));
        return count > 0;
    }

    /**
     * 删除角色
     *
     * @param unitId
     * @param roleId
     * @return
     */
    public boolean deleteRole(String unitId, String roleId) {
        ObjectId orgObjId = new ObjectId(unitId);
        ObjectId roleObjId = new ObjectId(roleId);
        return mongoTemplate.getCollection(SysRole.COLL_NAME)
                .updateOne(new Document(SysRole._ID, roleObjId),
                        new Document("$set", new Document(SysRole.STATUS, DataStatus.DELETE)))
                .getModifiedCount() > 0;
    }

    /**
     * 更新角色信息
     *
     * @param roleId
     * @param roleName
     * @param roleDesc
     * @return
     */
    public boolean updateRole(String orgId, String roleId, String roleName, String roleDesc) {
        Document filter = new Document(SysRole._ID, new ObjectId(roleId));
        Document update = new Document("$set", new Document(SysRole.NAME, roleName).append(SysRole.DESC, roleDesc));
        return mongoTemplate.getCollection(SysRole.COLL_NAME).updateOne(filter, update).getMatchedCount() > 0;
    }

    /**
     * 获得角色授权的菜单
     *
     * @param roleIdStr 角色ID
     * @return 菜单ID集合
     */
    @SuppressWarnings("unchecked")
    public List<ObjectId> getRoleAuthMenu(String roleIdStr) {
        ObjectId roleId = new ObjectId(roleIdStr);
        Document roleDoc = mongoTemplate.getCollection(SysRole.COLL_NAME).find(new Document(SysRole._ID, roleId)
                .append(SysRole.STATUS, DataStatus.NORMAL))
                .projection(Projections.include(SysRole.MENUS)).first();
        if (roleDoc == null) {
            return new ArrayList<ObjectId>();
        }

        List<ObjectId> idList = (List<ObjectId>) roleDoc.get(SysRole.MENUS);
        if (idList == null) {
            return new ArrayList<ObjectId>();
        }

        return idList;
    }

    /**
     * 设置角色的授权菜单
     *
     * @param roleIdStr 角色ID
     * @param menus     菜单ID集合
     * @return 设置是否成功
     */
    public boolean setRoleAuthMenu(String roleIdStr, Collection<String> menus) {
        ObjectId roleId = new ObjectId(roleIdStr);
        Document filter = new Document(SysRole._ID, roleId).append(SysRole.STATUS,
                DataStatus.NORMAL);

        List<ObjectId> menuIdList = new ArrayList<>();
        for (String str : menus) {
            if (!StringUtils.isEmpty(str)) {
                menuIdList.add(new ObjectId(str));
            }
        }
        return mongoTemplate.getCollection(SysRole.COLL_NAME).updateOne(filter, Updates.set(SysRole.MENUS, menuIdList))
                .getMatchedCount() > 0;
    }

    /**
     * 获得这个角色的资源状态清单
     *
     * @param user   操作员帐号，根据管理员帐号查询管理员所有的授权资源
     * @param roleId 被管理的角色，根据这个角色查询这个角色已经拥有的资源
     * @return 返回这个角色授权的资源状态
     */
    public List<Document> getRoleSelectMenu(User user, String roleId) {
        List<Document> allDoc = menuService.getUserAuthedMenu(user);
        List<ObjectId> menuIdList = getRoleAuthMenu(roleId);
        for (Document doc : allDoc) {
            doc.put("auth", false); // 标识是否已授权
            ObjectId oid = doc.getObjectId(SysMenu._ID);
            for (ObjectId mid : menuIdList) {
                if (oid.equals(mid)) {
                    doc.put("auth", true);
                    break;
                }
            }
        }

        return allDoc;
    }

    /**
     * 获得角色授权的接口
     *
     * @param roleIdStr 角色ID
     * @return 接口ID集合
     */
    @SuppressWarnings("unchecked")
    public List<ObjectId> getRoleAuthInterface(String roleIdStr) {
        ObjectId roleId = new ObjectId(roleIdStr);
        Document roleDoc = mongoTemplate.getCollection(SysRole.COLL_NAME)
                .find(new Document(SysRole._ID, roleId).append(SysRole.STATUS, 0))
                .projection(Projections.include(SysRole.INTERFACES)).first();
        if (roleDoc == null) {
            return new ArrayList<ObjectId>();
        }

        List<ObjectId> idList = (List<ObjectId>) roleDoc.get(SysRole.INTERFACES);
        if (idList == null) {
            return new ArrayList<ObjectId>();
        }

        return idList;
    }

    /**
     * 获得这个角色的资源状态清单
     *
     * @param user   管理员帐号，根据管理员帐号查询管理员所有的授权资源
     * @param roleId 被管理的角色，根据这个角色查询这个角色已经拥有的资源
     * @return 返回这个角色授权的资源状态
     */
    public List<Document> getRoleSelectInterface(User user, String roleId) {
        List<Document> allDoc = interfaceService.getUserAuthedInterface(user);
        List<ObjectId> interfaceIdList = getRoleAuthInterface(roleId);
        for (Document doc : allDoc) {
            doc.put("auth", false); // 标识是否已授权
            ObjectId oid = doc.getObjectId(SysInterface._ID);
            for (ObjectId mid : interfaceIdList) {
                if (oid.equals(mid)) {
                    doc.put("auth", true);
                    break;
                }
            }
        }
        return allDoc;
    }

    /**
     * 设置角色接口权限
     *
     * @param roleIdStr
     * @param interfaces
     * @return
     */
    public boolean setRoleAuthInterface(String roleIdStr, Collection<String> interfaces) {
        ObjectId roleId = new ObjectId(roleIdStr);
        Document filter = new Document(SysRole._ID, roleId);
        List<ObjectId> interfaseIdList = new ArrayList<ObjectId>();
        for (String str : interfaces) {
            if (!StringUtils.isEmpty(str)) {
                interfaseIdList.add(new ObjectId(str));
            }
        }
        return mongoTemplate.getCollection(SysRole.COLL_NAME)
                .updateOne(filter, Updates.set(SysRole.INTERFACES, interfaseIdList)).getMatchedCount() > 0;
    }

}
